﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using MonoTouch.SQLite;
using Android.OS;
using Newtonsoft.Json;

namespace LinkNote.Model
{
    public class BaseModel : Java.Lang.Object, IComparable<BaseModel>, IComparable, IEquatable<BaseModel>//, IDictionary<string, object>
    {
        [Ignore, JsonIgnore]
        public virtual int ID { get; set; }

        //public Bundle ToBundle()
        //{
        //    Bundle b = new Bundle();
        //    if (infos == null)
        //        infos = this.GetType().GetProperties();
        //    foreach (PropertyInfo pi in infos)
        //    {
        //        var ignore = pi.GetCustomAttributes(typeof(IgnoreAttribute), true).Length > 0;
        //        if (!pi.CanWrite || ignore)
        //            continue;

        //        object v = pi.GetValue(this, null);
        //        Type clrType = pi.PropertyType;
        //        if (clrType == typeof(Boolean) || clrType == typeof(Byte) || clrType == typeof(UInt16) || clrType == typeof(SByte) || clrType == typeof(Int16) || clrType == typeof(Int32))
        //        {
        //            b.PutInt(pi.Name, (int)v);
        //        }
        //        else if (clrType == typeof(UInt32) || clrType == typeof(Int64))
        //        {
        //            b.PutLong(pi.Name, (long)v);
        //        }
        //        else if (clrType == typeof(Single) || clrType == typeof(Double) || clrType == typeof(Decimal))
        //        {
        //            b.PutFloat(pi.Name, (float)v);
        //        }
        //        else if (clrType == typeof(String))
        //        {
        //            b.PutString(pi.Name, (string)v);
        //        }
        //        else if (clrType == typeof(DateTime))
        //        {
        //            b.PutLong(pi.Name, ((DateTime)v).Ticks);
        //        }
        //        else if (clrType.IsEnum)
        //        {
        //            b.PutInt(pi.Name, (int)v);
        //        } 
        //        else if (clrType == typeof(byte[]))
        //        {
        //            b.PutByteArray(pi.Name, (byte[])v) ;
        //        }
        //        else if (clrType == typeof(Guid))
        //        {
        //            b.PutString(pi.Name, v.ToString());
        //        }
        //    }
        //    return b;
        //}

        //public void Add(string key, object value)
        //{
        //    throw new NotImplementedException();
        //}

        //public bool ContainsKey(string key)
        //{
        //    throw new NotImplementedException();
        //}

        //public ICollection<string> Keys
        //{
        //    get { throw new NotImplementedException(); }
        //}

        //public bool Remove(string key)
        //{
        //    throw new NotImplementedException();
        //}

        //public bool TryGetValue(string key, out object value)
        //{
        //    throw new NotImplementedException();
        //}

        //public ICollection<object> Values
        //{
        //    get { throw new NotImplementedException(); }
        //}

        //static private PropertyInfo[] infos;
        //[Ignore, JsonIgnore]
        //public object this[string key]
        //{
        //    get
        //    {
        //        if (infos == null)
        //            infos = this.GetType().GetProperties();
        //        foreach(PropertyInfo pi in infos)
        //            if (pi.Name == key)
        //            {
        //                return pi.GetValue(this, null);
        //            }
        //        return null;
        //    }
        //    set
        //    {
        //        if (infos == null)
        //            infos = this.GetType().GetProperties();
        //        foreach (PropertyInfo pi in infos)
        //            if (pi.Name == key)
        //            {
        //                pi.SetValue(this, value, null);
        //            }
        //    }
        //}

        //public System.Collections.IEnumerator GetEnumerator()
        //{
        //    throw new NotImplementedException();
        //}

        //public void Add(KeyValuePair<string, object> item)
        //{
        //    throw new NotImplementedException();
        //}

        //public void Clear()
        //{
        //    throw new NotImplementedException();
        //}

        //public bool Contains(KeyValuePair<string, object> item)
        //{
        //    throw new NotImplementedException();
        //}

        //public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
        //{
        //    throw new NotImplementedException();
        //}

        //public int Count
        //{
        //    get { throw new NotImplementedException(); }
        //}

        //public bool IsReadOnly
        //{
        //    get { throw new NotImplementedException(); }
        //}

        //public bool Remove(KeyValuePair<string, object> item)
        //{
        //    throw new NotImplementedException();
        //}

        //IEnumerator<KeyValuePair<string, object>> IEnumerable<KeyValuePair<string, object>>.GetEnumerator()
        //{
        //    throw new NotImplementedException();
        //}

        public int CompareTo(BaseModel other)
        {
            if (this.ID == other.ID)
                return 0;
            else if (this.ID > other.ID)
                return 1;
            else
                return -1;
        }

        public int CompareTo(object obj)
        {
            if (obj == null)
                return -1;

            if (obj is Int32)
                return this.ID.CompareTo(obj);
            else
            {
                return CompareTo((BaseModel) obj);
            }
        }

        public bool Equals(BaseModel other)
        {
            return CompareTo(other) == 0;
        }

        public override bool Equals(object o)
        {
            return CompareTo(o) == 0;
        }

        public override int GetHashCode()
        {
            unchecked
            {
                return (base.GetHashCode() * 111) ^ ID;
            }
        }

        //public override string ToString()
        //{
        //    return string.Format("{0}:{1}", this.GetType().Name, this.ID);
        //}

        public static bool operator ==(BaseModel o1, BaseModel o2)
        {
            if (object.ReferenceEquals(o1, o2))
                return true;
            if (object.ReferenceEquals(o1, null) || object.ReferenceEquals(o2, null))
                return false;
            return o1.ID == o2.ID;
        }

        public static bool operator !=(BaseModel o1, BaseModel o2)
        {
            return !(o1 == o2);
        }
    }
}
